import javax.swing.*;
import java.io.*;
import java.net.*;
import java.text.*;

public class MainClient {
	/**
	 * @param args
	 */
	public static final int SOCKET_PORT = 9876;
	public static void main(String[] args) throws Exception {
		
		String ipString = getServerIP();
		
		Socket clientSocket = generateClientSocket(ipString);
		DataInputStream socketIn = new DataInputStream(clientSocket.getInputStream());
		DataOutputStream socketOut = new DataOutputStream(clientSocket.getOutputStream());		
		
		boolean quit=false;
		while (quit == false)
		{
			String command = getUserCommand();
			

			TestResults results;
			double megabytesPerSecond;
			switch(command){
			case "EXIT":
				JOptionPane.showMessageDialog(null, "Closing Client!");
				sendCommand('E', socketOut);
				socketIn.close();
				socketOut.close();
				clientSocket.close();
				System.exit(0);
			
			case "SHORT":
				sendCommand('S', socketOut);
				System.out.println(clientSocket.getPort() + " " + clientSocket.getRemoteSocketAddress().toString() + " " + clientSocket.isClosed());
				results = new TestResults();
				receiveData(socketIn, results);
				megabytesPerSecond = 1000.0*results.bytesTransferred/(results.milisecondsRequired*1048576);
				JOptionPane.showMessageDialog(null, "The short test took " + results.milisecondsRequired + "ms to send " + results.bytesTransferred/1024.0 + " KB.\nData transfer rate was " + megabytesPerSecond + " MB/s");
				break;
			case "LONG":
				sendCommand('L', socketOut);				
				results = new TestResults();
				receiveData(socketIn, results);
				megabytesPerSecond = 1000.0*results.bytesTransferred/(results.milisecondsRequired*1048576);
				JOptionPane.showMessageDialog(null, "The long test took " + results.milisecondsRequired + "ms to send " + results.bytesTransferred/1024.0 + " KB.\nData transfer rate was " + megabytesPerSecond + " MB/s");
				break;
			case "CUSTOM SERVER FILE":
				sendCommand('C', socketOut);				
				results = new TestResults();
				receiveData(socketIn, results);
				megabytesPerSecond = 1000.0*results.bytesTransferred/(results.milisecondsRequired*1048576);
				JOptionPane.showMessageDialog(null, "The custom test took " + results.milisecondsRequired + "ms to send " + results.bytesTransferred/1024.0 + " KB.\nData transfer rate was " + megabytesPerSecond + " MB/s");
				break;
			default:
				JOptionPane.showMessageDialog(null, "Invalid Input Somehow");
				break;
			}
		}
		clientSocket.close();
	}
	
	
	public static String getServerIP(){
		JOptionPane.showMessageDialog(null, "Welcome to the Client Application!");
		return JOptionPane.showInputDialog("Please enter the Server IP address:");
	}
	
	
	public static Socket generateClientSocket(String ipString) {
		Socket clientSocket = null;
		try {
			InetAddress ipAddress = InetAddress.getByName(ipString);
			clientSocket = new Socket(ipAddress, SOCKET_PORT);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return clientSocket;
	}

	
	private static String getUserCommand() {
		Object[] possibleValues = { "Short", "Long", "Custom Server File","Exit"};
		Object selectedValue = JOptionPane.showInputDialog(null, "Choose a test type:", "Input",JOptionPane.INFORMATION_MESSAGE, null,
				possibleValues, possibleValues[0]);
		return selectedValue.toString().trim().toUpperCase();
	}

	
	public static void sendCommand(char command, DataOutputStream socketOut) {
		try {
			socketOut.writeChar(command);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	
private static void receiveData(DataInputStream socketIn, TestResults results) {
		long startTime = 0, endTime = 0;
		try {
			String filename = "received" + System.currentTimeMillis();
			File outFile = new File(filename);
			FileOutputStream outputFileStream = new FileOutputStream(outFile);
			long fileSize = socketIn.readLong();
			byte[] buffer = new byte[1024];
			startTime = System.currentTimeMillis();
			
			long bytesReceived = 0;
			for(bytesReceived = socketIn.read(buffer); bytesReceived < fileSize; bytesReceived += socketIn.read(buffer))
			{
				outputFileStream.write(buffer);
			}
			
			endTime = System.currentTimeMillis();
			results.bytesTransferred = bytesReceived;
			results.milisecondsRequired = endTime-startTime;
			System.out.println("Received " + bytesReceived + " bytes.");
			System.out.println("Done.");
			outputFileStream.close();
			return;
			
		} catch (FileNotFoundException e1) {

			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		 

		
	}
	
}

class TestResults {
	long milisecondsRequired;
	long bytesTransferred;
}
